
import events from './events';

/**
 * 流程:
 * 1. monitor 需要添加告诉屏幕, 房间号
 * 2. 屏幕这里来创建资源、开启资源、绑定资源
 */
const PHASE_NO_READY = 0;
const PHASE_SEND_DANMU = 1;
const PHASE_SEND_CLOSE = 2;
const PHASE_READY = 3; // 转起来
const PHASE_PICKING = 4; // 抽取中
const PHASE_PICKED = 5; // 抽取完, 这个是由 UI 发起消息而转到的状态

class Lottery {
  phase = PHASE_NO_READY;
  /** 是否任何话都行 */
  any = true;
  words = '';

  /** @type {Candidate[]} 发弹幕的时候这个在填充 */
  participants = [];
  /** @type {Candidate[]} 在转的时候, 也就是 picking 时这个才有内容 */
  candidates = [];
  /** @type {Candidate} 选中了谁? */
  chosen = null;

  constructor(args) {
    this.context = args.context;
    this.context.subscribeOne(events.PHASE_PICKED,
        this.onPicked.bind(this), `Lottery#${events.PHASE_PICKED}`);
  }

  destroy() {
    this.context.removeSubscriber(`Lottery#${events.PHASE_PICKED}`);
  }

  updateWords(words) {
    this.words = words;
    this.any = words == '';
    this.context.releaseEvent(events.WORDS_UPDATED, {words, any: this.any});
  }

  onDanmuReceived(danmu) {
    if (this.phase != PHASE_SEND_DANMU) {
			return;
		}

    const uid = danmu.uId;
    if (this.participants.find(part => part.uid === uid)) {
      return;
    }

    const word = danmu.text;
    if (!this.any && this.words != word) {
      return;
    }
    const candidate = new Candidate(uid, danmu.uName);
    this.participants.push(candidate);
    this.context.releaseEvent(events.CANDIDATE_ADDED, candidate);
  }

  reset() {
    this.participants = [];
    this.candidates = [];
    this.chosen = null;
    this.phase = PHASE_NO_READY;
    this.context.releaseEvent(events.PHASE_RESET);
  }

  begin() {
    if (this.phase != PHASE_NO_READY && this.phase != PHASE_SEND_CLOSE && this.phase != PHASE_PICKED) {
      console.log('无法转换状态到 SEND_DANMU, 当前状态为', this.phase);
      return;
    }
    this.candidates = [];
    this.chosen = null;
    this.phase = PHASE_SEND_DANMU;
    this.context.releaseEvent(events.PHASE_BEGIN);
  }

  end() {
    if (this.phase != PHASE_SEND_DANMU && this.phase != PHASE_PICKING) {
      console.log('无法转换状态到 SEND_CLOSE, 当前状态为', this.phase);
      return;
    }
    this.candidates = [];
    this.chosen = null;
    this.phase = PHASE_SEND_CLOSE;
    this.context.releaseEvent(events.PHASE_END);
  }

  ready() { // 转起来
    if (this.phase === PHASE_PICKING) {
      console.log('无法转换状态到 READY, 当前状态为 PICKING');
      return;
    }
    if (this.phase === PHASE_PICKED) {
      for (let i = this.candidates.length - 1; i >= 0; i--) {
        let candidate = this.candidates[i];
        if (candidate.uid === this.chosen.uid) {
          this.candidates.splice(i, 1);
        }
      }
    } else {
      this.candidates = [].concat(this.participants);
    }

    if (this.candidates.length === 0) {
      console.log('弹幕人群还没人呢, 无法 ready');
      return;
    }
    while (this.candidates.length < 16) {
      this.candidates = this.candidates.concat(this.candidates);
    }
    this.shuffleCandidates();
    this.phase = PHASE_READY;
    this.chosen = null;
    this.context.releaseEvent(events.PHASE_READY);
  }

  picking() {
    if (this.phase != PHASE_READY) {
      console.log('无法转换状态到 SEND_CLOSE, 当前状态为', this.phase);
      return;
    }
    this.chosen = null;
    this.phase = PHASE_PICKING;
    this.context.releaseEvent(events.PHASE_PICKING);
  }

  onPicked(_, param) {
    this.phase = PHASE_PICKED;
    this.chosen = param.chosen;
    console.log('被选中的 candidate 是', this.chosen);
  }

  shuffleCandidates() {
    const candidates = this.candidates;
    for (let i = candidates.length-1; i>=0; i--) {
      let rIndex = Math.floor(Math.random()*(i+1));
      let temp = candidates[rIndex];
      candidates[rIndex] = candidates[i];
      candidates[i] = temp;
    }
  }
}

class Candidate {
  /**
   * @param {number} uid 
   * @param {string} uname 
   */
  constructor(uid, uname) {
    this.uid = uid;
    this.uname = uname;
  }
}

export {
  Lottery, Candidate,
  PHASE_NO_READY, PHASE_SEND_DANMU, PHASE_SEND_CLOSE, PHASE_READY, PHASE_PICKING, PHASE_PICKED,
};
